from typing import List
import os
import psutil
import requests
from urllib.parse import urlparse

from python_microservice_sdk import config
from python_microservice_sdk.utils.sub_module import find_sub_module, list_files


def get_instance_on(project_dir: str) -> psutil.Process:
    """判断项目实例是否启动，启动返回进程id，否则返回0

    Args:
        project_dir (str): 项目根目录

    Returns:
        process (psutil.Process): 实例进程
    """
    pid_file = os.path.join(project_dir, "pid")
    if not os.path.exists(pid_file):
        return None

    with open(pid_file, 'r') as fp:
        pid = int(fp.readline())

    try:
        process = psutil.Process(pid)
    except psutil.NoSuchProcess:
        return None

    for openfile in process.open_files():
        if os.path.samefile(openfile.path, pid_file):
            return process

    return None


def run(project_dir: str):
    # 先判断本地实例是否启动，如果本地实例启动则报错
    local_instance_process = get_instance_on(project_dir)
    if local_instance_process is not None:
        print("要在线更新所有上线微服务，必须先停止本地微服务实例的运行")
        exit(-1)

    config_module = find_sub_module("config", project_dir)
    if config_module is not None:
        cfg = getattr(config_module, "PYTHON_SERVICE_CONFIG", {})

    config.PYTHON_SERVICE_CONFIG.update(cfg)
    cfg = config.PYTHON_SERVICE_CONFIG

    eureka_server: str = cfg["eureka_server"]
    app_name: str = cfg["app_name"]
    update_paths: List[str] = cfg["metadata"]["update_paths"]

    filepaths = []
    for update_path in update_paths:
        filepaths.extend(list_files(update_path,
                                    excludes=[".recover", ".git", ".gitignore", "__pycache__", ".tmp"]))

    files = []
    for filepath in filepaths:
        files.append(("files", (filepath, open(filepath, mode='rb'))))

    parse_result = urlparse(eureka_server)

    update_url = "%s://%s:%d/%s" % (parse_result.scheme,
                                    parse_result.hostname,
                                    parse_result.port,
                                    "self_update")

    response = requests.post(
        url=update_url,
        data={
            "appName": app_name.upper(),
        },
        files=files
    )
    print(response.content)
